﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using kegg_service;
using Excel = Microsoft.Office.Interop.Excel;
using System.Net;
using System.Xml;
using System.Runtime.InteropServices;
using System.Diagnostics;
using QuickGraph;
using System.Runtime.Serialization.Formatters.Binary;
using MySql.Data.MySqlClient;

namespace BPP
{
    public partial class controller
    {
        public class read_model
        {

            public static List<Metabolites> listOfMetabolites = new List<Metabolites>();
            public static List<Reactions> listOfReactions = new List<Reactions>();
            static Form1 form = Form.ActiveForm as Form1;

            //release object from memory
            private static void releaseObject(object obj)
            {
                try
                {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
                    obj = null;
                }
                catch (Exception ex)
                {
                    obj = null;

                }
                finally
                {
                    GC.Collect();
                }
            }

            //get data from kegg by ec number
            static string GetKeddData(string ec_number)
            {
                //create document to return
                XmlDocument xmlDoc = new XmlDocument();

                //url of the service
                string url = "http://www.genome.jp/dbget-bin/www_bget?" + ec_number;

                // used to build entire input
                StringBuilder sb = new StringBuilder();

                // used on each read operation
                byte[] buf = new byte[8192];

                // prepare the web page we will be asking for
                HttpWebRequest request = (HttpWebRequest)
                    WebRequest.Create(url);

                // execute the request
                HttpWebResponse response = (HttpWebResponse)
                    request.GetResponse();

                // we will read data via the response stream
                Stream resStream = response.GetResponseStream();

                string tempString = null;
                int count = 0;

                do
                {
                    // fill the buffer with data
                    count = resStream.Read(buf, 0, buf.Length);

                    // make sure we read some data
                    if (count != 0)
                    {
                        // translate from bytes to ASCII text
                        tempString = Encoding.ASCII.GetString(buf, 0, count);

                        // continue building the string
                        sb.Append(tempString);
                    }
                }
                while (count > 0); // any more data to read?

                string s = sb.ToString();

                string reaction = "";
                try
                {
                    //44 - [RN:<a href="/dbget-bin/www_bget?rn:R01528">R01528</a>] get only reaction id
                    reaction = "rn:" + s.Substring(s.IndexOf("[RN:") + 44, 6);
                }
                catch (Exception ex)
                {
                }
                return reaction;
            }

            //reads excel model
            public static void ReadExcelModel(string path)
            {
                
                form.progressBar1.Minimum = 0;
                form.progressBar1.Maximum = 10;
                form.progressBar1.Value = 0;

                form.label1.Text = "Reading model...";

                Excel.Application xlApp;

                form.progressBar1.Value = 2;

                Excel.Workbook xlWorkBook;

                object misValue = System.Reflection.Missing.Value;

                form.progressBar1.Value = 3;

                xlApp = new Excel.Application();

                form.progressBar1.Value = 7;

                xlWorkBook =
                    xlApp.Workbooks.Open(path, 0, false, 5, "", "",
                        false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);

                form.progressBar1.Value = 10;

                form.label1.Text = "Reading metabolites...";

                //select data from metabolites sheet
                SelectMetabolites((Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1));

                form.label1.Text = "Reading reactions...";

                //select data from reaction sheet
                SelectReactions((Excel.Worksheet)xlWorkBook.Worksheets.get_Item(2));

                form.label1.Text = "Model is readed!";

                xlWorkBook.Save();

                xlWorkBook.Close();

                xlApp.Quit();

                releaseObject(xlWorkBook);

                releaseObject(xlApp);

                GC.WaitForPendingFinalizers();

                form.label1.Text = "Done! " + path.Substring(path.LastIndexOf("\\") + 1);
            }

            //select data from metabolites sheet
            private static void SelectMetabolites(Excel.Worksheet _xlWorkSheetMetabolites1)
            {
                Excel.Worksheet xlWorkSheetMetabolites1 = _xlWorkSheetMetabolites1;
                Excel.Range range = xlWorkSheetMetabolites1.UsedRange;

                form.progressBar1.Maximum = range.Rows.Count;
                form.progressBar1.Value = 0;

                string str;
                int rCnt = 0;

                //checking for null values in user.range
                int rowcount = 0;
                for (rCnt = 1; rCnt <= range.Rows.Count; rCnt++)
                {
                    if ((range.Cells[rCnt, 1] as Excel.Range).get_Value() == null)
                    {
                        rowcount = rCnt;
                        break;
                    }
                }

                //checking for null values in user.range
                int columcount = 0;
                for (rCnt = 1; rCnt <= range.Columns.Count; rCnt++)
                {
                    if ((range.Cells[1, rCnt] as Excel.Range).get_Value() == null)
                    {
                        columcount = rCnt;
                        break;
                    }
                }

                int counter;
                if (rowcount != 0)
                    counter = rowcount - 1;
                else
                    counter = range.Rows.Count;

                int countercol;
                if (columcount != 0)
                    countercol = columcount - 1;
                else
                    countercol = range.Columns.Count;

                string[] tmp = new string[countercol];

                //fill array of reactions
                for (int rowCnt = 2; rowCnt <= counter; rowCnt++)
                {
                    form.progressBar1.Value++;

                    for (rCnt = 1; rCnt <= countercol; rCnt++)
                    {
                        try
                        {
                            if ((range.Cells[rowCnt, rCnt] as Excel.Range).get_Value() != null)
                            {
                                str = (range.Cells[rowCnt, rCnt] as Excel.Range).get_Value().ToString();
                            }
                            else
                                str = "";
                            tmp[rCnt - 1] = str;
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.ToString());
                        }
                    }

                    listOfMetabolites.Add(new Metabolites(tmp));
                }

                releaseObject(xlWorkSheetMetabolites1);
            }

            //select data from reaction sheet
            private static void SelectReactions(Excel.Worksheet _xlWorkSheet)
            {
                Excel.Worksheet xlWorkSheet = _xlWorkSheet;
                Excel.Range range = xlWorkSheet.UsedRange;

                form.progressBar1.Maximum = range.Rows.Count;
                form.progressBar1.Value = 0;

                //checking for null values in user.range
                int rowcount = 0;
                for (int rCnt = 1; rCnt <= range.Rows.Count; rCnt++)
                {
                    if ((range.Cells[rCnt, 1] as Excel.Range).get_Value() == null)
                    {
                        rowcount = rCnt;
                        break;
                    }
                }
                int counter;
                if (rowcount != 0)
                    counter = rowcount - 1;
                else
                    counter = range.Rows.Count;

                //fill array of reactions
                for (int rCnt = 2; rCnt <= counter; rCnt++)
                {
                    string[] arr = new string[7];

                    try
                    {
                        form.progressBar1.Value++;

                        //reaction
                        if (!(range.Cells[rCnt, 3] as Excel.Range).get_Value().Contains("[e]") && ((range.Cells[rCnt, 13] as Excel.Range).get_Value() != null))
                        {
                            //abbreviation
                            if ((range.Cells[rCnt, 1] as Excel.Range).get_Value() != null)
                                arr[0] = (range.Cells[rCnt, 1] as Excel.Range).get_Value().ToString();
                            else
                                arr[0] = "";
                            //name
                            if ((range.Cells[rCnt, 2] as Excel.Range).get_Value() != null)
                                arr[1] = (range.Cells[rCnt, 2] as Excel.Range).get_Value().ToString();
                            else
                                arr[1] = "";
                            //reaction
                            if ((range.Cells[rCnt, 3] as Excel.Range).get_Value() != null)
                                arr[2] = (range.Cells[rCnt, 3] as Excel.Range).get_Value().ToString();
                            else
                                arr[2] = "";
                            //Subsystem
                            if ((range.Cells[rCnt, 7] as Excel.Range).get_Value() != null)
                                arr[3] = (range.Cells[rCnt, 7] as Excel.Range).get_Value().ToString();
                            else
                                arr[3] = "";
                            //reversible
                            if ((range.Cells[rCnt, 8] as Excel.Range).get_Value() != null)
                                arr[4] = (range.Cells[rCnt, 8] as Excel.Range).get_Value().ToString();
                            else
                                arr[4] = "";
                            //ec_number
                            if ((range.Cells[rCnt, 13] as Excel.Range).get_Value() != null)
                                arr[5] = (range.Cells[rCnt, 13] as Excel.Range).get_Value().ToString();
                            else
                                arr[5] = "";
                            //kegg_id
                            if ((range.Cells[rCnt, 16] as Excel.Range).get_Value() != null)
                                arr[6] = (range.Cells[rCnt, 16] as Excel.Range).get_Value().ToString();
                            else
                            {
                                ////array of reaction fields. are used 5 fields
                                string reaction_ec = "";

                                if (arr[5] != "")
                                    reaction_ec = arr[5].Trim();
                                else
                                {
                                    reaction_ec = "";
                                    arr[6] = arr[1];
                                }

                                if (reaction_ec != "")
                                {
                                    string[] reaction_kegg = controller.shared_functions.kegg.get_reactions_by_enzyme("ec:" + reaction_ec);

                                    if (reaction_kegg.Length == 0)
                                        arr[6] = reaction_ec;
                                    else if (reaction_kegg.Length > 1)
                                    {
                                        string kegg_answ = GetKeddData("ec:" + reaction_ec);

                                        arr[6] = kegg_answ;
                                    }
                                    else
                                    {
                                        arr[6] = reaction_kegg[0];
                                    }
                                }

                            }

                            (range.Cells[rCnt, 16] as Excel.Range).Value = arr[6];



                            listOfReactions.Add(new Reactions(arr));
                        }

                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.ToString());
                    }
                }

                releaseObject(xlWorkSheet);
            }

          

           
            public static BidirectionalGraph<object, IEdge<object>> h1 = new BidirectionalGraph<object, IEdge<object>>();


            /// <summary>
            /// Create graph with values from the database
            /// </summary>
            public static void CreateGraphToVisualize(List<Reactions> list)
            {

                for (int i = 0; i < list.Count; i++)
                {

                    //add vertices to graph aka the nodes
                    shared_functions.model_graph.AddVertex(list[i].Kegg);


                    string[] charSeparators = new string[] { "->" };

                    string[] sides = list[i].Reaction.Split(charSeparators, StringSplitOptions.RemoveEmptyEntries);


                    // dobavitj v edges nazvanie reacii i metaboliti

                    string[] metabolSeparators = new string[] { " + " };
                    string[] metabolitesL = sides[0].Split(metabolSeparators, StringSplitOptions.RemoveEmptyEntries);

                    string remove_metabolites = "nadph h nadh nad atp adp h2o co2 nadp";

                    //udalitj  nadph h nadh nad atp adp h2o co2 
                    try
                    {

                        foreach (string str in metabolitesL)
                        {

                            string tmp = str.Trim();
                            tmp = tmp.TrimStart(' ');
                            if (tmp.Contains(" "))
                                tmp = tmp.Substring(tmp.IndexOf(" ") + 1);

                            if (!remove_metabolites.Contains(str))
                            {
                               


                                string keggId = "cpd:" +
                                    listOfMetabolites.Find(delegate(Metabolites e) { return e.Abbreviation == tmp; }).KEGG_ID;

                                shared_functions.model_graph.AddVertex(keggId);

                                shared_functions.model_graph.AddEdge(new Edge<object>(keggId, list[i].Kegg));

                                if (list[i].Reversible == "1")
                                    shared_functions.model_graph.AddEdge(new Edge<object>(list[i].Kegg, keggId));
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                    }

                    string[] metabolitesR = sides[1].Split(metabolSeparators, StringSplitOptions.RemoveEmptyEntries);

                    try
                    {
                        foreach (string str in metabolitesR)
                        {
                            string tmp = str.Trim();
                            tmp = tmp.TrimStart(' ');
                             if (tmp.Contains(" "))
                                    tmp = tmp.Substring(tmp.IndexOf(" ") + 1);

                            if (!remove_metabolites.Contains(tmp))
                            {
                                
                                   

                                string keggId = "cpd:" +
                                    listOfMetabolites.Find(delegate(Metabolites e) { return e.Abbreviation == tmp; }).KEGG_ID;

                                shared_functions.model_graph.AddVertex(keggId);

                                shared_functions.model_graph.AddEdge(new Edge<object>(list[i].Kegg, keggId));

                                if (list[i].Reversible == "1")
                                    shared_functions.model_graph.AddEdge(new Edge<object>(keggId, list[i].Kegg));
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                    }
                }



                //rabotaet v byte
                // mozhno peredatj mezdu applkacijami


                //  byte[] a = ObjectToByteArray((object)h);

                //    object ss = ByteArrayToObject(a);

                //   _graphtovisualize = h;  // (IBidirectionalGraph<Object, IEdge<object>>)ss;

            }
            /// <summary>
            /// Create graph with values from the database
            /// </summary>
        }
    }
}
